home *** CD-ROM | disk | FTP | other *** search
/ Internet Info 1994 March / Internet Info CD-ROM (Walnut Creek) (March 1994).iso / networking / ip / ka9q / alpha.arc / SLIP.C < prev    next >
C/C++ Source or Header  |  1988-07-26  |  5KB  |  239 lines

  1. /* Send and receive IP datagrams on serial lines. Compatible with SLIP
  2.  * under Berkeley Unix.
  3.  */
  4. #include <stdio.h>
  5. #include "global.h"
  6. #include "mbuf.h"
  7. #include "iface.h"
  8. #include "ax25.h"
  9. #include "slip.h"
  10. #include "asy.h"
  11. #include "trace.h"
  12.  
  13. int asy_ioctl();
  14. int kiss_ioctl();
  15. int slip_send();
  16. void doslip();
  17. int asy_output();
  18.  
  19. /* Slip level control structure */
  20. struct slip slip[ASY_MAX];
  21.  
  22. /* Send routine for point-to-point slip
  23.  * This is a trivial function since there is no slip link-level header
  24.  */
  25. int
  26. slip_send(data,interface,gateway,precedence,delay,throughput,reliability)
  27. struct mbuf *data;        /* Buffer to send */
  28. struct interface *interface;    /* Pointer to interface control block */
  29. int32 gateway;            /* Ignored (SLIP is point-to-point) */
  30. char precedence;
  31. char delay;
  32. char throughput;
  33. char reliability;
  34. {
  35.     if(interface == NULLIF){
  36.         free_p(data);
  37.         return -1;
  38.     }
  39.     dump(interface,IF_TRACE_OUT,TRACE_IP,data);
  40.     return (*interface->raw)(interface,data);
  41. }
  42. /* Send a raw slip frame -- also trivial */
  43. int
  44. slip_raw(interface,data)
  45. struct interface *interface;
  46. struct mbuf *data;
  47. {
  48.     /* Queue a frame on the slip output queue and start transmitter */
  49.     return slipq(interface->dev,data);
  50. }
  51. /* Encode a raw packet in slip framing, put on link output queue, and kick
  52.  * transmitter
  53.  */
  54. static int
  55. slipq(dev,data)
  56. int16 dev;        /* Serial line number */
  57. struct mbuf *data;    /* Buffer to be sent */
  58. {
  59.     register struct slip *sp;
  60.     struct mbuf *slip_encode(),*bp;
  61.     void asy_start();
  62.  
  63.     if((bp = slip_encode(data)) == NULLBUF)
  64.         return -1;    
  65.  
  66.     sp = &slip[dev];
  67.     enqueue(&sp->sndq,bp);
  68.     sp->sndcnt++;
  69.     if(sp->tbp == NULLBUF)
  70.         asy_start(dev);
  71.     return 0;
  72. }
  73. /* Start output, if possible, on asynch device dev */
  74. static void
  75. asy_start(dev)
  76. int16 dev;
  77. {
  78.     register struct slip *sp;
  79.  
  80.     if(!stxrdy(dev))
  81.         return;        /* Transmitter not ready */
  82.  
  83.     sp = &slip[dev];
  84.     if(sp->tbp != NULLBUF){
  85.         /* transmission just completed */
  86.         free_p(sp->tbp);
  87.         sp->tbp = NULLBUF;
  88.     }
  89.     if(sp->sndq == NULLBUF)
  90.         return;    /* No work */
  91.  
  92.     sp->tbp = dequeue(&sp->sndq);
  93.     sp->sndcnt--;
  94.     asy_output(dev,sp->tbp->data,sp->tbp->cnt);
  95. }
  96. /* Encode a packet in SLIP format */
  97. static
  98. struct mbuf *
  99. slip_encode(bp)
  100. struct mbuf *bp;
  101. {
  102.     struct mbuf *lbp;    /* Mbuf containing line-ready packet */
  103.     register char *cp;
  104.     char c;
  105.  
  106.     /* Allocate output mbuf that's twice as long as the packet.
  107.      * This is a worst-case guess (consider a packet full of FR_ENDs!)
  108.      */
  109.     lbp = alloc_mbuf(2*len_mbuf(bp) + 2);
  110.     if(lbp == NULLBUF){
  111.         /* No space; drop */
  112.         free_p(bp);
  113.         return NULLBUF;
  114.     }
  115.     cp = lbp->data;
  116.  
  117.     /* Flush out any line garbage */
  118.     *cp++ = FR_END;
  119.  
  120.     /* Copy input to output, escaping special characters */
  121.     while(pullup(&bp,&c,1) == 1){
  122.         switch(uchar(c)){
  123.         case FR_ESC:
  124.             *cp++ = FR_ESC;
  125.             *cp++ = T_FR_ESC;
  126.             break;
  127.         case FR_END:
  128.             *cp++ = FR_ESC;
  129.             *cp++ = T_FR_END;
  130.             break;
  131.         default:
  132.             *cp++ = c;
  133.         }
  134.     }
  135.     *cp++ = FR_END;
  136.     lbp->cnt = cp - lbp->data;
  137.     return lbp;
  138. }
  139. /* Process incoming bytes in SLIP format
  140.  * When a buffer is complete, return it; otherwise NULLBUF
  141.  */
  142. static
  143. struct mbuf *
  144. slip_decode(dev,c)
  145. int16 dev;    /* Slip unit number */
  146. char c;        /* Incoming character */
  147. {
  148.     struct mbuf *bp;
  149.     register struct slip *sp;
  150.  
  151.     sp = &slip[dev];
  152.     switch(uchar(c)){
  153.     case FR_END:
  154.         bp = sp->rbp;
  155.         sp->rbp = NULLBUF;
  156.         sp->rcnt = 0;
  157.         return bp;    /* Will be NULLBUF if empty frame */
  158.     case FR_ESC:
  159.         sp->escaped = 1;
  160.         return NULLBUF;
  161.     }
  162.     if(sp->escaped){
  163.         /* Translate 2-char escape sequence back to original char */
  164.         sp->escaped = 0;
  165.         switch(uchar(c)){
  166.         case T_FR_ESC:
  167.             c = FR_ESC;
  168.             break;
  169.         case T_FR_END:
  170.             c = FR_END;
  171.             break;
  172.         default:
  173.             sp->errors++;
  174.             break;
  175.         }
  176.     }
  177.     /* We reach here with a character for the buffer;
  178.      * make sure there's space for it
  179.      */
  180.     if(sp->rbp == NULLBUF){
  181.         /* Allocate first mbuf for new packet */
  182.         if((sp->rbp1 = sp->rbp = alloc_mbuf(SLIP_ALLOC)) == NULLBUF)
  183.             return NULLBUF; /* No memory, drop */
  184.         sp->rcp = sp->rbp->data;
  185.     } else if(sp->rbp1->cnt == SLIP_ALLOC){
  186.         /* Current mbuf is full; link in another */
  187.         if((sp->rbp1->next = alloc_mbuf(SLIP_ALLOC)) == NULLBUF){
  188.             /* No memory, drop whole thing */
  189.             free_p(sp->rbp);
  190.             sp->rbp = NULLBUF;
  191.             sp->rcnt = 0;
  192.             return NULLBUF;
  193.         }
  194.         sp->rbp1 = sp->rbp1->next;
  195.         sp->rcp = sp->rbp1->data;
  196.     }
  197.     /* Store the character, increment fragment and total
  198.      * byte counts
  199.      */
  200.     *sp->rcp++ = c;
  201.     sp->rbp1->cnt++;
  202.     sp->rcnt++;
  203.     return NULLBUF;
  204. }
  205. /* Process SLIP line I/O */
  206. void
  207. doslip(interface)
  208. struct interface *interface;
  209. {
  210.     char c;
  211.     struct mbuf *bp;
  212.     int16 dev;
  213.     int16 asy_recv();
  214.  
  215.     dev = interface->dev;
  216.     /* Process any pending input */
  217.     while(asy_recv(dev,&c,1) != 0)
  218.         if((bp = slip_decode(dev,c)) != NULLBUF)
  219.             (*slip[dev].recv)(interface,bp);
  220.  
  221.     /* Kick the transmitter if it's idle */
  222.     if(stxrdy(dev))
  223.         asy_start(dev);
  224. }
  225. /* Unwrap incoming SLIP packets -- trivial operation since there's no
  226.  * link level header
  227.  */
  228. void
  229. slip_recv(interface,bp)
  230. struct interface *interface;
  231. struct mbuf *bp;
  232. {
  233.     int ip_route();
  234.  
  235.     /* By definition, all incoming packets are "addressed" to us */
  236.     dump(interface,IF_TRACE_IN,TRACE_IP,bp);
  237.     ip_route(bp,0);
  238. }
  239.